package com.example.project.projectspringcloud;

import com.example.project.projectspringcloud.common.Constants;
import com.example.project.projectspringcloud.dao.sys.SysConfigMapper;
import com.example.project.projectspringcloud.dao.video.VideoMapper;
import com.example.project.projectspringcloud.entity.RespBody;
import com.example.project.projectspringcloud.entity.discountcoupon.DiscountCoupon;
import com.example.project.projectspringcloud.entity.order.Order;
import com.example.project.projectspringcloud.entity.sys.SysConfig;
import com.example.project.projectspringcloud.entity.video.Video;
import com.example.project.projectspringcloud.service.discountcoupon.DiscountCouponService;
import com.example.project.projectspringcloud.service.order.OrderService;
import com.example.project.projectspringcloud.utils.DeviceUtil;
import com.example.project.projectspringcloud.utils.RedisUtil;
import com.example.project.projectspringcloud.utils.TencentVideoUtil;
import com.google.gson.Gson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.servlet.ModelAndView;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Set;

@ControllerAdvice
@EnableScheduling
@EnableSwagger2
@EnableTransactionManagement
@SpringBootApplication
public class Application {

    private static final Logger logger = LoggerFactory.getLogger(Application.class);
    @Autowired
    private VideoMapper videoMapper;
    @Autowired
    private SysConfigMapper sysConfigMapper;
    @Resource
    private RedisUtil redisUtil;
    @Autowired
    private OrderService orderService;
    @Autowired
    private DiscountCouponService discountCouponService;

    /**
     * 启动
     * ==============================================================================
     *
     * @param args
     */
    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(Application.class);
        application.setBannerMode(Banner.Mode.OFF);
        application.run(args);
        logger.info("====================Project lualu started!====================");
    }

    /**
     * 错误页面
     * ==============================================================================
     *
     * @param request
     * @return
     */
    @GetMapping(value = {"302", "400", "403", "404", "500", "502", "error"})
    public String error(HttpServletRequest request) {
        String errorCode = (String) request.getAttribute("status");
        logger.error(errorCode);
        return "error/" + errorCode;
    }

    @ExceptionHandler(Exception.class)
    public Object errorHandler(HttpServletRequest request,
                               HttpServletResponse response, Exception e) throws Exception {
        logger.error("URL: {}", request.getRequestURL());
        logger.error("系统异常: ", e);

        if (DeviceUtil.isMobile(request.getHeader("USER-AGENT"))) {
            response.getWriter().write(new RespBody(RespBody.ERROR_CODE, null, e.getMessage()).toString());
            response.getWriter().flush();
            return null;
        }

        ModelAndView mav = new ModelAndView();
        mav.addObject("exception", e);
        mav.addObject("url", request.getRequestURL());

        mav.setViewName("redirect:/error");
        return mav;
    }

    /**
     * 自动清理redis中过期视频, 每30分钟检查
     * ==============================================================================
     */
    @Scheduled(cron = "0 0/30 * * * ?")
    public void videoExpireCheck() throws Exception {
        List<SysConfig> sysConfigList = sysConfigMapper.selectAll(new SysConfig("tencentcloud"));
        Set<Integer> videoIds = videoMapper.selectAllVideoUrl(new Video());
        videoIds.forEach(t -> {
            if (!redisUtil.hasKey(Constants.VIDEO_CACHE_PREFIX + t)) {
                Video video = videoMapper.selectOne(new Video(t));
                try {
                    redisUtil.set(Constants.VIDEO_CACHE_PREFIX + video.getId(),
                            new Gson().toJson(TencentVideoUtil.getTCPlayParam(video, false, sysConfigList, redisUtil, false)),
                            82800);
                } catch (Exception e) {
                    logger.error("videoExpireCheck", e);
                }
            }
        });
    }

    /**
     * 检查过期订单
     * ==============================================================================
     */
    @Scheduled(cron = "0 0/10 * * * ?")
    public void orderExamine() {
        List<Order> orders = orderService.list(null, new Order());
    }

    /**
     * 检查过期优惠券
     * ==============================================================================
     */
    @Scheduled(cron = "0 0/10 * * * ?")
    public void discountCouponExamine() {
        List<DiscountCoupon> discountCoupons = discountCouponService.expira(new DiscountCoupon());
        discountCoupons.forEach(t -> {
            // 设置过期状态
            t.setStatus(3);
            discountCouponService.status(t.getId(), t.getStatus());
        });
    }
}
